/*
* File: maze.c
* ------------
* This program solves a maze by recursive backtracking.
*/

#include <stdio.h>
#include "genlib.h"
#include "graphics.h"
#include "mazelib.h"
#include "simpio.h"

/*withoutUnmark is not using UnmarkSquare,
* withUnMark is using UnmarkSquare. 
*/
enum {
	withoutUnmark = 0,
	withUnMark
};

/* Private function prototypes */
static bool SolveMaze(pointT pt, int *nRecurs, int useUnmark);
static pointT AdjacentPoint(pointT pt, directionT dir);
static string choose(void);
static void printGroupMembers();

/* Main program */

main(){

	string choice;
	int numRecursions = 0;

	InitGraphics();
	printGroupMembers();
	SetPauseTime(0.002);

	choice = choose();

	ReadMazeMap(choice);

	if (SolveMaze(GetStartPosition(), &numRecursions, withUnMark)) {
		printf("The marked squares show a solution path.\n");
		printf("Number of recursions with UnmarkSquare: %d.\n", numRecursions);

		numRecursions = 0;
		SolveMaze(GetStartPosition(), &numRecursions, withoutUnmark);
		printf("Number of recursions without UnmarkSquare: %d.\n", numRecursions);
	}
	else {
		printf("No solution exists.\n");
	}
}

/*
* Procedure: printGroupMembers
* Usage: printGroupMembers();
* --------------------------------
* This procedure prints the authors of this
* program to screen.
*/
static void printGroupMembers(){

	printf("This program was developed by: ");
	printf("Jim Glansk, S141587, ");
	printf("Henrik Wistbacka, S142066\n");
}


/*
* Function: SolveMaze
* Usage: if (SolveMaze(pt)) . . .
* -------------------------------
* This function attempts to generate a solution to the current
* maze from point pt.  SolveMaze returns TRUE if the maze has
* a solution and FALSE otherwise.  The implementation uses
* recursion to solve the submazes that result from marking the
* current square and moving one step along each open passage.
*/

static bool SolveMaze(pointT pt, int *nRecurs, int useUnmark)
{
	directionT dir;
	*nRecurs += 1;
	

	if (OutsideMaze(pt)) return (TRUE);
	if (IsMarked(pt)) return (FALSE);
	MarkSquare(pt);
	for (dir = North; dir <= West; dir++) {
		if (!WallExists(pt, dir)) {
			if (SolveMaze(AdjacentPoint(pt, dir), nRecurs, useUnmark)) {
				UnmarkSquare(pt);
				return (TRUE);

			}
		}
	}

	if (useUnmark)
		UnmarkSquare(pt);

	return (FALSE);
}

/*
* Function: AdjacentPoint
* Usage: newpt = AdjacentPoint(pt, dir);
* --------------------------------------
* This function returns the pointT that results from moving
* one square from pt in the direction specified by dir.  For
* example, if pt is the point (1,1), AdjacentPoint(pt, East)
* would return the point (2,1).
*/

static pointT AdjacentPoint(pointT pt, directionT dir)
{
	pointT newpt;

	newpt = pt;
	switch (dir) {
	case North: newpt.y++; break;
	case East:  newpt.x++; break;
	case South: newpt.y--; break;
	case West:  newpt.x--; break;;
	}
	return (newpt);
}

/*
* Procedure: choose
* Usage: filename = choose();
* --------------------------------
* This function returns the name of the 
* file the user chooses.
*/
static string choose(void){

	int choice;

	printf("Select one of the following maps:\n");
	printf("1. Pathlen.\n");
	printf("2. Example.\n");
	printf("3. Unmark.\n");

	while (TRUE){
		choice = GetInteger();
		if (choice < 1 || choice > 4){
			break;
		}

		switch (choice){
		case 1:
			return("pathlen.maz");
		case 2:
			return("example.maz");
		case 3:
			return("unmark.maz");
		default:
			printf("Please input valid map");
		}
	}
}